home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / bin / debconf-apt-progress < prev    next >
Encoding:
Text File  |  2007-03-24  |  6.9 KB  |  300 lines

  1. #!/usr/bin/perl -w
  2. # This file was preprocessed, do not edit!
  3.  
  4.  
  5. use strict;
  6. use POSIX;
  7. use Fcntl;
  8. use Getopt::Long;
  9. use Debconf::Client::ConfModule ();
  10.  
  11. my ($config, $start, $from, $to, $stop);
  12. my ($logfile, $logstderr);
  13.  
  14. sub checkopen (@) {
  15.     my $file = $_[0];
  16.     my $fd = POSIX::open($file, &POSIX::O_RDONLY);
  17.     defined $fd or die "$0: can't open $_[0]: $!\n";
  18.     return $fd;
  19. }
  20.  
  21. sub checkclose ($) {
  22.     my $fd = $_[0];
  23.     unless (POSIX::close($fd)) {
  24.         return if $! == &POSIX::EBADF;
  25.         die "$0: can't close fd $fd: $!\n";
  26.     }
  27. }
  28.  
  29. sub checkdup2 ($$) {
  30.     my ($oldfd, $newfd) = @_;
  31.     checkclose($newfd);
  32.     POSIX::dup2($oldfd, $newfd)
  33.         or die "$0: can't dup fd $oldfd to $newfd: $!\n";
  34. }
  35.  
  36. sub nocloexec (*) {
  37.     my $fh = shift;
  38.     my $flags = fcntl($fh, F_GETFD, 0);
  39.     fcntl($fh, F_SETFD, $flags & ~FD_CLOEXEC);
  40. }
  41.  
  42. sub reservefds (@) {
  43.     my $null = checkopen('/dev/null');
  44.     my $close = 1;
  45.     for my $fd (@_) {
  46.         if ($null == $fd) {
  47.             $close = 0;
  48.         } else {
  49.             checkclose($fd);
  50.             checkdup2($null, $fd);
  51.         }
  52.     }
  53.     if ($close) {
  54.         checkclose($null);
  55.     }
  56. }
  57.  
  58. sub envnonempty ($) {
  59.     my $name = shift;
  60.     return (exists $ENV{$name} and $ENV{$name} ne '');
  61. }
  62.  
  63. sub start_debconf (@) {
  64.     if (! $ENV{DEBIAN_HAS_FRONTEND}) {
  65.         if (envnonempty('DEBCONF_DB_REPLACE')) {
  66.             $ENV{DEBCONF_APT_PROGRESS_DB_REPLACE} =
  67.                 $ENV{DEBCONF_DB_REPLACE};
  68.         }
  69.         if (envnonempty('DEBCONF_DB_OVERRIDE')) {
  70.             $ENV{DEBCONF_APT_PROGRESS_DB_OVERRIDE} =
  71.                 $ENV{DEBCONF_DB_OVERRIDE};
  72.         }
  73.  
  74.         $ENV{DEBCONF_DB_REPLACE} = 'configdb';
  75.         $ENV{DEBCONF_DB_OVERRIDE} = 'Pipe{infd:none outfd:none}';
  76.  
  77.         @ARGV = @_;
  78.     }
  79.  
  80.     import Debconf::Client::ConfModule;
  81. }
  82.  
  83. sub passthrough (@) {
  84.     my $priority = Debconf::Client::ConfModule::get('debconf/priority');
  85.  
  86.     defined(my $pid = fork) or die "$0: can't fork: $!\n";
  87.     if (!$pid) {
  88.         close STATUS_READ;
  89.         close COMMAND_WRITE;
  90.         $^F = 6; # avoid close-on-exec
  91.         checkdup2(0, 5);
  92.         if (exists $ENV{DEBCONF_REDIR} and $ENV{DEBCONF_REDIR}) {
  93.             checkdup2(3, 6);
  94.             checkclose(3);
  95.         } else {
  96.             checkdup2(1, 6);
  97.         }
  98.         if (fileno(COMMAND_READ) != 0) {
  99.             checkdup2(fileno(COMMAND_READ), 0);
  100.             close COMMAND_READ;
  101.         }
  102.         if (fileno(APT_LOG) != 1) {
  103.             checkclose(1);
  104.             checkdup2(fileno(APT_LOG), 1);
  105.         }
  106.         if (fileno(APT_LOG) != 2) {
  107.             checkclose(2);
  108.             checkdup2(fileno(APT_LOG), 2);
  109.         }
  110.         close APT_LOG;
  111.         delete $ENV{DEBIAN_HAS_FRONTEND};
  112.         delete $ENV{DEBCONF_REDIR};
  113.         delete $ENV{DEBCONF_SYSTEMRC};
  114.         delete $ENV{DEBCONF_PIPE}; # just in case ...
  115.         $ENV{DEBIAN_FRONTEND} = 'passthrough';
  116.         $ENV{DEBIAN_PRIORITY} = $priority;
  117.         $ENV{DEBCONF_READFD} = 5;
  118.         $ENV{DEBCONF_WRITEFD} = 6;
  119.         $ENV{APT_LISTCHANGES_FRONTEND} = 'none';
  120.         exec @_;
  121.     }
  122.  
  123.     close STATUS_WRITE;
  124.     close COMMAND_READ;
  125.     return $pid;
  126. }
  127.  
  128. sub run_progress ($$@) {
  129.     my $from = shift;
  130.     my $to = shift;
  131.     my $command = shift;
  132.     local (*STATUS_READ, *STATUS_WRITE);
  133.     local (*COMMAND_READ, *COMMAND_WRITE);
  134.     local *APT_LOG;
  135.  
  136.     Debconf::Client::ConfModule::progress(
  137.         'INFO', 'debconf-apt-progress/preparing');
  138.  
  139.     reservefds(4, 5, 6);
  140.  
  141.     pipe STATUS_READ, STATUS_WRITE or die "$0: can't create status pipe: $!";
  142.     checkdup2(fileno(STATUS_WRITE), 4);
  143.     open STATUS_WRITE, '>&=4'
  144.         or die "$0: can't reopen STATUS_WRITE as fd 4: $!";
  145.     nocloexec(\*STATUS_WRITE);
  146.     pipe COMMAND_READ, COMMAND_WRITE or die "$0: can't create command pipe: $!";
  147.     nocloexec(\*COMMAND_READ);
  148.     use IO::Handle;
  149.     COMMAND_WRITE->autoflush(1);
  150.  
  151.     if (defined $logfile) {
  152.         open APT_LOG, '>>', $logfile
  153.             or die "$0: can't open $logfile: $!";
  154.     } elsif ($logstderr) {
  155.         open APT_LOG, '>&STDERR'
  156.             or die "$0: can't duplicate stderr: $!";
  157.     } else {
  158.         open APT_LOG, '>', '/dev/null'
  159.             or die "$0: can't open /dev/null: $!";
  160.     }
  161.     nocloexec(\*APT_LOG);
  162.  
  163.     my $pid = passthrough $command,
  164.         '-o', 'APT::Status-Fd=4',
  165.         '-o', 'APT::Keep-Fds::=5',
  166.         '-o', 'APT::Keep-Fds::=6',
  167.         @_;
  168.  
  169.     while (<STATUS_READ>) {
  170.         chomp;
  171.         my ($status, $pkg, $percent, $description) = split ':', $_, 4;
  172.  
  173.         my ($min, $len);
  174.         if ($status eq 'dlstatus') {
  175.             $min = 0;
  176.             $len = 15;
  177.         }
  178.         elsif ($status eq 'pmstatus') {
  179.             $min = 15;
  180.             $len = 85;
  181.         }
  182.         elsif ($status eq 'media-change') {
  183.             Debconf::Client::ConfModule::subst(
  184.                 'debconf-apt-progress/media-change', 'MESSAGE',
  185.                 $description);
  186.             my @ret = Debconf::Client::ConfModule::input(
  187.                 'critical', 'debconf-apt-progress/media-change');
  188.             $ret[0] == 0 or
  189.                 die "Can't display media change request!\n";
  190.             Debconf::Client::ConfModule::go();
  191.             print COMMAND_WRITE "\n" || die "can't talk to command fd: $!";
  192.             next;
  193.         }
  194.         else {
  195.             next;
  196.         }
  197.  
  198.         $percent = ($percent * $len / 100 + $min);
  199.         $percent = ($percent * ($to - $from) / 100 + $from);
  200.         $percent =~ s/\..*//;
  201.         Debconf::Client::ConfModule::progress('SET', $percent);
  202.         Debconf::Client::ConfModule::subst(
  203.             'debconf-apt-progress/info', 'DESCRIPTION',
  204.             $description);
  205.         Debconf::Client::ConfModule::progress(
  206.             'INFO', 'debconf-apt-progress/info');
  207.     }
  208.  
  209.     waitpid $pid, 0;
  210.     my $status = $?;
  211.  
  212.     Debconf::Client::ConfModule::progress('SET', $to);
  213.  
  214.     return ($status >> 8);
  215. }
  216.  
  217. sub start_bar ($$) {
  218.     my ($from, $to) = @_;
  219.     Debconf::Client::ConfModule::progress(
  220.         'START', $from, $to, 'debconf-apt-progress/title');
  221.     Debconf::Client::ConfModule::progress(
  222.         'INFO', 'debconf-apt-progress/preparing');
  223. }
  224.  
  225. sub stop_bar () {
  226.     Debconf::Client::ConfModule::progress('STOP');
  227.     Debconf::Client::ConfModule::stop();
  228. }
  229.  
  230. if (envnonempty('DEBCONF_APT_PROGRESS_DB_REPLACE')) {
  231.     $ENV{DEBCONF_DB_REPLACE} = $ENV{DEBCONF_APT_PROGRESS_DB_REPLACE};
  232. } else {
  233.     delete $ENV{DEBCONF_DB_REPLACE};
  234. }
  235. if (envnonempty('DEBCONF_APT_PROGRESS_DB_OVERRIDE')) {
  236.     $ENV{DEBCONF_DB_OVERRIDE} = $ENV{DEBCONF_APT_PROGRESS_DB_OVERRIDE};
  237. } else {
  238.     delete $ENV{DEBCONF_DB_OVERRIDE};
  239. }
  240.  
  241. my @saved_argv = @ARGV;
  242.  
  243. my $result = GetOptions('config'    => \$config,
  244.             'start'     => \$start,
  245.             'from=i'    => \$from,
  246.             'to=i'      => \$to,
  247.             'stop'      => \$stop,
  248.             'logfile=s' => \$logfile,
  249.             'logstderr' => \$logstderr);
  250.  
  251. unless ($start) {
  252.     if (defined $from and not defined $to) {
  253.         die "$0: --from requires --to\n";
  254.     } elsif (defined $to and not defined $from) {
  255.         die "$0: --to requires --from\n";
  256.     }
  257. }
  258.  
  259. my $mutex = 0;
  260. ++$mutex if $config;
  261. ++$mutex if $start;
  262. ++$mutex if $stop;
  263. if ($mutex > 1) {
  264.     die "$0: must use only one of --config, --start, or --stop\n";
  265. }
  266.  
  267. if (($config or $stop) and (defined $from or defined $to)) {
  268.     die "$0: cannot use --from or --to with --config or --stop\n";
  269. }
  270.  
  271. start_debconf(@saved_argv) unless $config;
  272.  
  273. my $status = 0;
  274.  
  275. if ($config) {
  276.     print <<'EOF';
  277. DEBCONF_APT_PROGRESS_DB_REPLACE="$DEBCONF_DB_REPLACE"
  278. DEBCONF_APT_PROGRESS_DB_OVERRIDE="$DEBCONF_DB_OVERRIDE"
  279. export DEBCONF_APT_PROGRESS_DB_REPLACE DEBCONF_APT_PROGRESS_DB_OVERRIDE
  280. DEBCONF_DB_REPLACE=configdb
  281. DEBCONF_DB_OVERRIDE='Pipe{infd:none outfd:none}'
  282. export DEBCONF_DB_REPLACE DEBCONF_DB_OVERRIDE
  283. EOF
  284. } elsif ($start) {
  285.     $from = 0 unless defined $from;
  286.     $to = 100 unless defined $to;
  287.     start_bar($from, $to);
  288. } elsif (defined $from) {
  289.     $status = run_progress($from, $to, @ARGV);
  290. } elsif ($stop) {
  291.     stop_bar();
  292. } else {
  293.     start_bar(0, 100);
  294.     $status = run_progress(0, 100, @ARGV);
  295.     stop_bar();
  296. }
  297.  
  298. exit $status;
  299.  
  300.